#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libavutil/log.h>
#include <libavutil/opt.h>

#define RTSP_URL "rtsp://127.0.0.1:554/test"

int main(int argc, char *argv[]) {
    if (argc < 2) {
        fprintf(stderr, "Usage: %s <input_file>\n", argv[0]);
        return -1;
    }

    const char *input_file = argv[1];

    // 注册所有的编解码器和格式
    av_register_all();
    avformat_network_init();

    AVFormatContext *input_ctx = NULL;
    AVFormatContext *output_ctx = NULL;

    // 打开输入文件
    if (avformat_open_input(&input_ctx, input_file, NULL, NULL) < 0) {
        fprintf(stderr, "Could not open input file: %s\n", input_file);
        return -1;
    }

    // 查找输入流信息
    if (avformat_find_stream_info(input_ctx, NULL) < 0) {
        fprintf(stderr, "Could not find stream information\n");
        avformat_close_input(&input_ctx);
        return -1;
    }

    // 创建输出上下文
    avformat_alloc_output_context2(&output_ctx, NULL, "rtsp", RTSP_URL);
    if (!output_ctx) {
        fprintf(stderr, "Could not create output context\n");
        avformat_close_input(&input_ctx);
        return -1;
    }

    // 复制输入流到输出流
    for (int i = 0; i < input_ctx->nb_streams; i++) {
        AVStream *in_stream = input_ctx->streams[i];
        AVStream *out_stream = avformat_new_stream(output_ctx, NULL);
        if (!out_stream) {
            fprintf(stderr, "Failed to allocate output stream\n");
            avformat_close_input(&input_ctx);
            avformat_free_context(output_ctx);
            return -1;
        }

        // 复制流参数
        avcodec_parameters_copy(out_stream->codecpar, in_stream->codecpar);
        out_stream->codecpar->codec_tag = 0; // 清除 codec_tag
    }

    // 打开输出 RTSP 流
    if (avio_open(&output_ctx->pb, RTSP_URL, AVIO_FLAG_WRITE) < 0) {
        fprintf(stderr, "Could not open output URL: %s\n", RTSP_URL);
        avformat_close_input(&input_ctx);
        avformat_free_context(output_ctx);
        return -1;
    }

    // 写文件头
    if (avformat_write_header(output_ctx, NULL) < 0) {
        fprintf(stderr, "Error occurred when writing header\n");
        avformat_close_input(&input_ctx);
        avformat_free_context(output_ctx);
        return -1;
    }

    // 读取输入帧并推送到 RTSP
    AVPacket pkt;
    while (av_read_frame(input_ctx, &pkt) >= 0) {
        // 重新映射到输出流
        pkt.stream_index = 0; // 这里需要根据实际流索引进行调整
        av_interleaved_write_frame(output_ctx, &pkt);
        av_packet_unref(&pkt);
    }

    // 写文件尾
    av_write_trailer(output_ctx);

    // 清理
    avformat_close_input(&input_ctx);
    avio_closep(&output_ctx->pb);
    avformat_free_context(output_ctx);

    return 0;
}
